package com.analyse.stock.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.analyse.stock.config.MailConfig;
import com.analyse.stock.form.MailInfoForm;
import com.analyse.stock.form.PickStockQueryForm;
import com.analyse.stock.model.StockInfoModel;
import com.analyse.stock.model.StockKlineDailyModel;
import com.analyse.stock.service.IBoardIndexDaily;
import com.analyse.stock.service.IPickStockAnalyse;
import com.analyse.stock.service.IStockInfo;
import com.analyse.stock.service.IStockKlineDaily;
import com.analyse.stock.utils.MailUtil;
import com.analyse.stock.utils.StockAnalyzer;
import com.analyse.stock.vo.AnomalVO;
import com.analyse.stock.vo.PickStockVO;
import com.analyse.stock.vo.ProfitLostStatVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.ta4j.core.indicators.SMAIndicator;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author youyaohua
 */
@Slf4j
@Service
public class PickStockAnalyseService implements IPickStockAnalyse {

    @Resource
    private IStockInfo stockInfo;

    @Resource
    private IStockKlineDaily stockKlineDaily;

    @Resource
    private IBoardIndexDaily boardIndexDaily;

    @Resource
    private MailConfig mailConfig;

    @Override
    public List<PickStockVO> pickStock(PickStockQueryForm queryForm) {
        queryForm.setCurrentDate(DateUtil.format(DateUtil.date(), DatePattern.NORM_DATE_FORMAT));
        if(StringUtils.isBlank(queryForm.getStartDate())){
            //往前推30天
            queryForm.setStartDate(DateUtil.format(
                    DateUtil.offsetDay(DateUtil.date(),-30), DatePattern.NORM_DATE_FORMAT));
        }
        List<PickStockVO> list = stockInfo.pickStock(queryForm);
        if(CollUtil.isEmpty(list)){
            return Lists.newArrayList();
        }
        list.forEach(e->System.out.println(JSONObject.toJSONString(e)));
        return list;
    }

    @Override
    public List<PickStockVO> detect(PickStockQueryForm queryForm) {
        /*if(CollUtil.isEmpty(queryForm.getStockCodes())){
            return Lists.newArrayList();
        }*/
        List<StockInfoModel> list = stockInfo.getStockList(queryForm.getStockCodes());
        if(CollUtil.isEmpty(list)){
            return Lists.newArrayList();
        }
        if(StringUtils.isBlank(queryForm.getStartDate())){
            //往前推30天
            queryForm.setStartDate(DateUtil.format(
                    DateUtil.offsetDay(DateUtil.date(),-300), DatePattern.NORM_DATE_FORMAT));
        }
        List<ProfitLostStatVO> stats = Lists.newArrayList();
        // Calculate average volume based on 3 days
        int avgDays = 3;
        // Volume must be 1.5x the average
        double volumeMultiplier = 1.5d;
        // Price increase less than 0.5%
        double priceThreshold = 0.5d;

        // 计算主力资金平均值的天数
        int avgFundDays = 5;
        // 异动判断倍数
        double anomalyMultiplier = 2.0d;

        // 上影线长度至少是实体的2倍
        double shadowMultiplier = 1.5d;
        // 上影线占总波动范围的比例至少是70%
        double shadowProportion = 0.5d;

        List<PickStockVO> pickList = Lists.newArrayList();
        for(StockInfoModel model : list){
            List<StockKlineDailyModel> dailyModels =
                    stockKlineDaily.getStockKlineDailyList(model.getStockCode(),queryForm.getStartDate(),"");
            if(CollUtil.isEmpty(dailyModels)){
                continue;
            }
            SMAIndicator indicator = boardIndexDaily.getIndexSMAValue("000001",1,5,queryForm.getStartDate());
            List<AnomalVO> anomalyDates = Lists.newArrayList();

            //1、放量滞涨判断
            /*Set<AnomalVO> stags = StockAnalyzer.detectVolumeStagnation(dailyModels,avgDays, volumeMultiplier, priceThreshold);
            if(CollUtil.isNotEmpty(stags)){
                anomalyDates.addAll(stags);
            }
            //2、资金异动判断
            List<FundFlowHistoryModel> fundFlowHistorys = fundFlowHistory.getFundFlowHistoryList(model.getStockCode(),queryForm.getStartDate());
            List<AnomalVO> anomalList = StockAnalyzer.detectFundFlowAnomalies(fundFlowHistorys,avgFundDays, anomalyMultiplier);
            if(CollUtil.isNotEmpty(anomalList)){
                anomalyDates.addAll(anomalList);
            }*/
            //3、高位长上影线判断
            /*List<AnomalVO> longUppers = StockAnalyzer.detectLongUpperShadows(dailyModels,shadowMultiplier, shadowProportion);
            if(CollUtil.isNotEmpty(longUppers)){
                anomalyDates.addAll(longUppers);
            }

            List<AnomalVO> kdResult = StockAnalyzer.detectKD(dailyModels);
            if(CollUtil.isNotEmpty(kdResult)){
                anomalyDates.addAll(kdResult);
            }
            List<AnomalVO> rsiResult = StockAnalyzer.detectRSISellRule(dailyModels,6,12);
            if(CollUtil.isNotEmpty(rsiResult)){
                anomalyDates.addAll(rsiResult);
            }
            List<AnomalVO> sarResult = StockAnalyzer.detectSAR(dailyModels);
            if(CollUtil.isNotEmpty(sarResult)){
                anomalyDates.addAll(sarResult);
            }*/
            //TradingStrategyUtil.execSMAStrategy(dailyModels);
            /*List<AnomalVO> macdResult = StockAnalyzer.detectMACD(dailyModels,12,26);
            if(CollUtil.isNotEmpty(macdResult)){
                anomalyDates.addAll(macdResult);
            }*/
            //StockAnalyzer.detectTrend(dailyModels);
            try{
                ProfitLostStatVO statVO = StockAnalyzer.detectWR(dailyModels,42,indicator);
                stats.add(statVO);
            }catch (Exception ex){
                log.error("### 股票：{}--{},执行WR时出错 error:{}",
                        model.getStockName(),model.getStockCode(),ex.getMessage(),ex);
            }
            /*List<AnomalVO> result = StockAnalyzer.moveCalcTrend(anomalyDates,2);
            log.info("## 股票：{}--{}，异动日期：{}",model.getStockCode(),model.getStockName(),result);
            pickList.add(PickStockVO.me(model.getStockCode(),model.getStockName(),result));*/
        }
        List<ProfitLostStatVO> profitList = stats.stream().filter(e->e.getProfitLostAmt().compareTo(BigDecimal.ZERO)>0).collect(Collectors.toList());
        log.info("##股票总数：{}， 盈利的股票数：{}",stats.size(),profitList.size());
        log.info("##股票总数：{}， 亏损的的股票数：{}",stats.size(),(stats.size()-profitList.size()));
        String content = StrUtil.format("股票总数：{}， 盈利的股票数：{}",stats.size(),profitList.size());
        MailUtil.senderAsync(MailInfoForm.me(mailConfig,"检测通知"+queryForm.getStockCodes(),content));
        return pickList;
    }
}
